#pragma once
#include "common.hpp"
#include "log.hpp"
#include "addr.hpp"
#include <jsoncpp/json/json.h>
#include "sock.hpp"
const string sep = "\r\n";
class request;
class response;
using func = function<response(request)>;
class request
{
public:
    request() {}
    request(int x, int y, char oper) : _a(x), _b(y), _operator(oper) {}
    string serialize() // 报文序列化：
    {
        Json::Value root;
        root["x"] = _a;
        root["y"] = _b;
        root["oper"] = _operator;
        Json::FastWriter wr;
        return wr.write(root);
    }
    bool deserialize(string &mess) // 报文反序列化：
    {
        Json::Reader r;
        Json::Value root;
        bool ok = r.parse(mess, root);
        if (ok)
        {
            _a = root["x"].asInt();
            _b = root["y"].asInt();
            _operator = root["oper"].asInt();
        }
        return ok;
    }
 

    int geta() { return _a; }
    int getb() { return _b; }
    char getoper() { return _operator; }

    ~request() {}

private:
    int _a;
    int _b;
    char _operator;
};

class response
{
public:
    response() {}
    response(int res, int co) : _result(res), _code(co)
    {
    }
    void setcode(int c)
    {
        _code = c;
    }
    void setresult(int r)
    {
        _result = r;
    }
    string serialize()
    {
        Json::Value root;
        root["res"] = _result;
        root["code"] = _code;
        Json::FastWriter wr;
        return wr.write(root);
    }
    bool deserialize(string &mess)
    {
        Json::Reader r;
        Json::Value root;
        bool ok = r.parse(mess, root);
        if (ok)
        {
            _result = root["res"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }
    int getres() { return _result; }
    int getcode() { return _code; }
    void show_ans(){
        cout << "计算结果是：" << getres() << " 标志码是：" << getcode() <<" (备注:code为0计算成功,其他结果不可靠！)"<< endl;
    }
    ~response() {}

private:
    int _result;
    int _code = 0; // 默认成功计算就是0；否则按照规定处理
    // 0：正确计算 1：除0错误 2：mod0错误
};

class protocol
{

public:
    protocol() {}
    protocol(func tackle) : _tackle(tackle) {}
    void Encode(string &mess) // 给json报文加上报头： 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
    {
        mess = (to_string(mess.size()) + sep + mess + sep);
    }
    bool Decode(string &mess, string *json_mess) // 从缓冲区mess中读取到指定序列的字符串作为真正的json串；然后把它从缓冲区删除方便下一次读取
    {   if(!mess.size()) return 0;
        int pos = mess.find(sep.c_str(), 0); // find用法与substr相反
        string sz = mess.substr(0, pos);     // 找不到与能找到最后如果不合适都会return 0
        int sz_int = stoi(sz);
        int serialize_len = sep.size() * 2 + sz_int + sz.size(); // 封装后的报文实际长度
        if (serialize_len > mess.size())                         // 读取长度与实际长度比较
            return 0;
        *json_mess = mess.substr(pos + 2, sz_int);
        mess.erase(0, serialize_len); // 及时清除读完的缓冲区buff内容方便下一次读取
        return 1;
    }
int  getresponse(unique_ptr<Socket> &us)
    {
        while (1)
        {
            //从客户端的r缓冲区进行读取：
            string bf;
          int n=  us->Recv(bf);
          if(!n) {
            use_log(loglevel::DEBUG) << " 服务端异常!";
                exit(SERVER_EXIT);
          }
            string jn;
            //解码
            bool dans = Decode(bf, &jn);
            if (!dans)
                continue;
            //进行反序列化：
            response p;
            bool ok = p.deserialize(jn);
            if (!ok)
            {
                use_log(loglevel::DEBUG) << " response 反序列化失败!";
                continue;
            }
            //来到这一定完成了计算：
            p.show_ans();
            return 0;
        }
    }
    void getrequest(shared_ptr<Socket> &sock, inetaddr &client)
    {
        while (1)
        {
            string message; // 读取到的缓冲区（不一定就是序列化封装好的数据）
            // 1·从对应sock的r缓冲区读取数据
            int n = sock->Recv(message);

            if (n < 0)
            {
                use_log(loglevel::DEBUG) << client.get_userinfo() << " 读取异常!";
                return;
            }
            if (n == 0)
            {
                use_log(loglevel::DEBUG) << client.get_userinfo() << " QUIT!"; // 一般客户端退出；即结束后面关掉fd即可
               exit( CLINET_EXIT);
            }
            // 读到东西了：但是是面向字节流的可能不完整或者多了；但是每次一开始读到的一定是从最前面开始的：
            // // 5
            // 50
            // 50\r
            // 50\r\n
            // 50\r\n{"x": 10, "

            //  50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n :封装好报头信息再去发送这样好解析；因此我们最后解析得到的应该是这个样子
            string jn;
            // 2·进行正确提取：
            while (Decode(message, &jn))//如果我们读过来的缓冲区解析后还有完整报文那就继续解析直到不完整后才去r缓冲区读取
            {
                // jn:已经提取出来的json序列串：
                request rt;
                // 3·发序列化：
                bool ok = rt.deserialize(jn);
                if (!ok)
                {
                    use_log(loglevel::DEBUG) << " request 反序列化失败!";
                    continue;
                }
                // 4·执行业务：
                response ans = _tackle(rt); // 回调业务函数

                // 5·序列化处理：
                string sd = ans.serialize();
                // 6·封装报头处理：
                Encode(sd);
                // 7·进行发送：
                sock->Send(sd);
            }
        }
    }
    ~protocol()
    {
    }

private:
    func _tackle;
};